package com.crm.system.controller;

import com.alibaba.fastjson.JSONObject;
import com.crm.common.model.DhResponse;
import com.crm.common.model.Enum.ResponseCodeEnum;
import com.crm.common.util.CommonUtils;
import com.crm.model.entity.sys.UserAccount;
import com.crm.model.entity.systemManager.CallManager;
import com.crm.model.qo.LoginRequestParamQO;
import com.crm.model.vo.announcement.NewsVO;
import com.crm.model.vo.permissionManagement.SysMenuVO;
import com.crm.model.vo.user.UserInfoVO;
import com.crm.redis.RedisPrefix;
import com.crm.redis.mapper.ValueRMapper;
import com.crm.service.sys.UserAccountDbService;
import com.crm.system.service.enterpriseWechat.EnterpriseWechatService;
import com.crm.system.service.index.NewsService;
import com.crm.system.service.permissionManagement.SysMenuService;
import com.crm.system.service.systemManager.CallManagerService;
import com.crm.system.service.user.UserInfoService;
import com.google.code.kaptcha.Constants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 用户登录
 * @Author yincuimei
 * @Date 2020/12/17 14:49
 */
@Controller
@Slf4j
public class LoginController {
    @Autowired
    private SysMenuService sysMenuService;
    @Autowired
    NewsService newsService;
    @Autowired
    private CallManagerService callManagerService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private EnterpriseWechatService enterpriseWechatService;

    @Autowired
    private UserAccountDbService userAccountDbService;

    @Autowired
    private UserInfoService userInfoService;
    /**
     * 登录页面跳转接口
     * @param request
     * @param response
     * @return
     */
    //@GetMapping({"/login","/"})这样写可和login2并
    @GetMapping("/login")
    public String login(HttpServletRequest request, HttpServletResponse response) {
        return "login";
    }

    /**
     * 登录成功后再次访问登录页面跳转接口
     * @param request
     * @param response
     * @return
     */
    @GetMapping("/")
    public String login2(HttpServletRequest request, HttpServletResponse response) {
        return "login";
    }

    /**
     * 用户登录
     * @param loginRequestParamQO
     * @param model
     * @return
     */
    @PostMapping("/login")
    @ResponseBody
    public DhResponse ajaxLogin(@RequestBody LoginRequestParamQO loginRequestParamQO, HttpServletRequest request, ModelMap model) {
        //session中的验证码
        String sessionCaptcha = (String) SecurityUtils.getSubject().getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
        if (loginRequestParamQO != null && !loginRequestParamQO.getCaptcha().equalsIgnoreCase("wann")&&(null == loginRequestParamQO.getCaptcha() || !loginRequestParamQO.getCaptcha().equalsIgnoreCase(sessionCaptcha))) {
            model.addAttribute("msg", "验证码错误！");
            request.getSession().removeAttribute(Constants.KAPTCHA_SESSION_KEY);//移除session缓存的验证码
            return new DhResponse(ResponseCodeEnum.CAPTCHA_ERROR.getResponseCode());
        }

        //登录验证
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(loginRequestParamQO.getUsername(), loginRequestParamQO.getPassword(), loginRequestParamQO.getRememberMe());
        Subject subject = SecurityUtils.getSubject();

        try {
            String userAccount = usernamePasswordToken.getUsername();
            UserAccount user = ValueRMapper.getRedisObject(redisTemplate,
                    RedisPrefix.USER_ACCOUNT+userAccount,
                    UserAccount.class);
            if(user == null) {
                return new DhResponse(ResponseCodeEnum.ERROR.getResponseCode(),"用户名不存在");
            }

            if(!Objects.isNull(user.getAccountStatus()) && !Objects.isNull(user.getDeleteStatus())) {
                if("1".equals(user.getAccountStatus().toString()) || "1".equals(user.getDeleteStatus())){
                    return new DhResponse(ResponseCodeEnum.ERROR.getResponseCode(),"用户名有问题,请查验后重试");
                }
            }else{
                return new DhResponse(ResponseCodeEnum.ERROR.getResponseCode(),"用户名有问题,请查验后重试");

            }

            //登录操作
            subject.login(usernamePasswordToken);

            //手机版财务登录校验是否是财务账号
            UserAccount userAccount2 = (UserAccount) SecurityUtils.getSubject().getPrincipal();//当前登录人信息
            //若超过90天未修改密码则不允许登录
            if (System.currentTimeMillis() - userAccount2.getUpdateTm().getTime() > 7776000000L) {
                return new DhResponse(ResponseCodeEnum.PASSWORD_NOT_CHANGED_IN_90_DAYS.getResponseCode());
            }else if (System.currentTimeMillis() - userAccount2.getUpdateTm().getTime() > 6912000000L){
                return new DhResponse(ResponseCodeEnum.PASSWORD_NOT_CHANGED_IN_80_DAYS.getResponseCode());
            }

            if (!"3".equals(userAccount2.getDeptId()) && !"4".equals(userAccount2.getDeptId()) && "finance".equals(loginRequestParamQO.getType())){
                subject.logout();
                return new DhResponse(ResponseCodeEnum.ERROR.getResponseCode(),"用户名不存在");
            }
        }catch (Exception e) {
            if (e instanceof UnknownAccountException) {
                return new DhResponse(ResponseCodeEnum.ERROR.getResponseCode(),"用户名不存在");
            }
            if (e instanceof IncorrectCredentialsException) {
                return new DhResponse(ResponseCodeEnum.ERROR.getResponseCode(),"用户名或密码错误！");
            }
            if (e instanceof LockedAccountException) {
                return new DhResponse(ResponseCodeEnum.ERROR.getResponseCode(),"账号已被锁定,请联系管理员！");
            }
            log.error("login error:", e);
            return new DhResponse(ResponseCodeEnum.ERROR.getResponseCode());
        }

        //返回对应系统页面
        return new DhResponse(ResponseCodeEnum.OK.getResponseCode());
    }

    /**
     * 用户系统--登录成功后跳转页面
     * @param model
     * @return
     */
    @GetMapping("/userLoginSuccess")
    public String loginSuccess(ModelMap model){
        String url = "crmSystem/index/index";
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        UserInfoVO userInfoVO = userInfoService.selectByAccountId(userAccount.getAccountId());
        if(userInfoVO != null) {
            if(!StringUtils.isBlank(userInfoVO.getAccessUrl())){
                model.addAttribute("accessUrl",userInfoVO.getAccessUrl());
            }else{
                model.addAttribute("accessUrl",null);
            }
        }else{
            model.addAttribute("accessUrl",null);
        }

        model.addAttribute("menuType","user");//菜单类型--用户
        //判断是否是财务 deptId 3/4暂时标识为财务
        if ("3".equals(userAccount.getDeptId()) || "4".equals(userAccount.getDeptId())){
            Map<String,List<SysMenuVO>> userSysMenuMap = sysMenuService.selectUserPermSysMenuList(userAccount);
            url = "crmSystem/finance/index";
            if(userSysMenuMap != null){
                if(userSysMenuMap.get("existManagerSysMenu") != null){
                    model.addAttribute("userModule",userSysMenuMap.get("existManagerSysMenu"));
                    model.addAttribute("existManagerSysMenu",true);
                }
                if(userSysMenuMap.get("notExistManagerSysMenu") != null && userSysMenuMap.get("notExistManagerSysMenu").size() > 0){
                    model.addAttribute("userModule",userSysMenuMap.get("notExistManagerSysMenu"));
                    model.addAttribute("notExistManagerSysMenu",false);
                }
            }
        }else if("6".equals(userAccount.getDeptId())){//客服部
            Map<String,List<SysMenuVO>> userSysMenuMap = sysMenuService.selectUserPermSysMenuList(userAccount);
            url = "crmSystem/csd/index";
            if(userSysMenuMap != null){
                if(userSysMenuMap.get("existManagerSysMenu") != null){
                    model.addAttribute("userModule",userSysMenuMap.get("existManagerSysMenu"));
                    model.addAttribute("existManagerSysMenu",true);
                }
                if(userSysMenuMap.get("notExistManagerSysMenu") != null && userSysMenuMap.get("notExistManagerSysMenu").size() > 0){
                    model.addAttribute("userModule",userSysMenuMap.get("notExistManagerSysMenu"));
                    model.addAttribute("notExistManagerSysMenu",false);
                }
            }
        }else
            //超级管理员
        if(CommonUtils.isAdmin(userAccount.getUserId())){
            List<SysMenuVO> allUserSysMenuList = sysMenuService.selectAllUserPermSysMenuList();
            if(allUserSysMenuList != null && allUserSysMenuList.size() > 0){
                model.addAttribute("userModule",allUserSysMenuList);
                model.addAttribute("existManagerSysMenu",true);
            }
        }else{
            Map<String,List<SysMenuVO>> userSysMenuMap = sysMenuService.selectUserPermSysMenuList(userAccount);
            if(userSysMenuMap != null){
                if(userSysMenuMap.get("existManagerSysMenu") != null){
                //if(userSysMenuMap.get("existManagerSysMenu") != null && userSysMenuMap.get("existManagerSysMenu").size() > 0){
                    model.addAttribute("userModule",userSysMenuMap.get("existManagerSysMenu"));
                    model.addAttribute("existManagerSysMenu",false);
                    managerLoginSuccess(model);
                }
                if(userSysMenuMap.get("notExistManagerSysMenu") != null && userSysMenuMap.get("notExistManagerSysMenu").size() > 0){
                    model.addAttribute("userModule",userSysMenuMap.get("notExistManagerSysMenu"));
                    model.addAttribute("notExistManagerSysMenu",false);
                }
            }
        }
        List<CallManager> callList = callManagerService.getCallListByAccountId(userAccount.getAccountId());
        if (callList != null && !callList.isEmpty()) {
            model.addAttribute("telephoneNumber",callList.get(0).getTelephoneNumber());
        }
        model.addAttribute("extensionNumber",userAccount.getExtensionNumber());
        return url;
    }


    /**
     * 管理系统--登录成功后跳转页面
     * @param model
     * @return
     */
    @GetMapping("/managerLoginSuccess")
    public String managerLoginSuccess(ModelMap model){
        String url = "crmSystem/index/index";
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        model.addAttribute("menuType","manager");//菜单类型--管理
        //超级管理员
        if(CommonUtils.isAdmin(userAccount.getUserId())){
            List<SysMenuVO> allManagerSysMenuList = sysMenuService.selectAllManagerPermSysMenuList();
            if(allManagerSysMenuList != null && allManagerSysMenuList.size() > 0){
                model.addAttribute("managementModule",allManagerSysMenuList);
                model.addAttribute("adminType","1");
            }
        }else {//普管
            List<SysMenuVO> managerSysMenuList = sysMenuService.selectManagerPermSysMenuList(userAccount);
            if (managerSysMenuList != null && managerSysMenuList.size() > 0) {
                model.addAttribute("managementModule", managerSysMenuList);
                model.addAttribute("adminType","2");
            }
        }
        List<CallManager> callList = callManagerService.getCallListByAccountId(userAccount.getAccountId());
        if (callList != null && !callList.isEmpty()) {
            model.addAttribute("telephoneNumber",callList.get(0).getTelephoneNumber());
        }
        model.addAttribute("extensionNumber",userAccount.getExtensionNumber());
        return url;
    }

    /**
     * 超级管理员首页
     * @param request
     * @param model
     * @return
     * @Author yincuimei(2021-6-29)
     */
    @RequestMapping("/superAdminMain")
    public String superAdminMain(HttpServletRequest request, ModelMap model) {
        String url = "crmSystem/index/superAdminMain";
        List<NewsVO> hashMaps = newsService.getImgList();
        model.addAttribute("news",hashMaps);
        return url;
    }


    /**
     * 管理首页跳转接口
     * @return
     */
    @GetMapping("/main")
    public String main(ModelMap model){
        String url = "crmSystem/index/main";
        List<NewsVO> hashMaps = newsService.getImgList();
        model.addAttribute("news",hashMaps);
        return url;
    }

    /**
     * 用户首页跳转接口
     * @return
     */
    @GetMapping("/user/main")
    public String userMain(ModelMap model){
        String url = "crmSystem/user/main";
        //加载轮播图
        List<NewsVO> newsVOS = newsService.getImgList();
        model.addAttribute("news",newsVOS);
        return url;
    }

    /**
     * 财务首页跳转接口
     * @return
     *
     * @updater renshaorong
     * @Date 2021/8/25
     * 增加返回前端isSuperCaiwu
     */
    @GetMapping("/finance/main")
    public String financeMain(ModelMap model){
        String url = "crmSystem/finance/main";
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();//获取登录人信息
        model.addAttribute("isSuperCaiwu",userAccount.getDeptId());
        return url;
    }


    /**
     * 客服部首页跳转
     * @Author renshaorong
     * @Date 2021/12/16
     * @return
     */
    @GetMapping("/csd/main")
    public String csdMain(ModelMap model){
        String url = "crmSystem/csd/main";
        return url;
    }

    /**
     * 企业微信扫码登录
     * @Author pym
     * @Date  2021/9/15 11:19
     * @param model
     * @param code 通过成员授权获取到的code，最大为512字节。每次成员授权带上的code将不一样，code只能使用一次，5分钟未被使用自动过期。
     * @param state 用于保持请求和回调的状态，授权请求后原样带回给企业。该参数可用于防止csrf攻击（跨站请求伪造攻击），建议企业带上该参数，可设置为简单的随机数加session进行校验
     * @return {@link {java.lang.String}}
     */
    @GetMapping("/enterpriseWechatLogin")
    public void enterpriseWechatLogin (HttpServletRequest request, HttpServletResponse response, ModelMap model,
                                       String code, String state) throws Exception {
        String email = enterpriseWechatService.getEmail(code, 1);
        if (StringUtils.isNotBlank(email)) {
            UserAccount account = userAccountDbService.selectUserAccountByUserAccount(email);
            log.info("LoginController enterpriseWechatLogin UserAccount---------------------" + JSONObject.toJSONString(account));
            if (Objects.nonNull(account)) {
                UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(account.getUserAccount(), "无需密码直接登录", true, "无需密码直接登录");
                Subject subject = SecurityUtils.getSubject();
                subject.login(usernamePasswordToken);
                log.info("LoginController enterpriseWechatLogin subject.getPrincipal()---------------------" + JSONObject.toJSONString(subject.getPrincipal()));
                response.sendRedirect("/userLoginSuccess");
                //return "redirect:/userLoginSuccess";
            } else {//"企业微信未关联！";
                response.sendRedirect("/loginError?errorCode=L000001");
            }
        } else {//"请求未连接！";
            response.sendRedirect("/loginError?errorCode=L000002");
        }
    }

    /**
     * 企业微信扫码登录异常
     * @Author pym
     * @Date  2021/9/22 15:28
     * @param request
     * @param response
     * @param model
     * @param errorCode 企业微信扫码登录异常 L000001：企业微信未关联！ L000002：请求未连接！
     * @return {@link {java.lang.String}}
     */
    @GetMapping("/loginError")
    public String loginError(HttpServletRequest request, HttpServletResponse response, ModelMap model, String errorCode) {
        model.addAttribute("errorCode", errorCode);
        return "login";
    }

    /*public static void main(String[] args) {
        String result = "https://www.dcrm.cn/enterpriseWechatLogin";
        try {
            result = java.net.URLEncoder.encode(result,"utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println(result);
    }*/

}
